package common;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.TreeMap;

import modules.configuration.GameConf;
import modules.gameCommunication.DataCenter;
import objects.Account;
import objects.Cell;
import objects.Character;
import objects.Fight;
import objects.Item;
import objects.Map;
import objects.Monster;
import objects.MonsterGroup;
import objects.Trigger;

public class PacketFormatter {

    private ResultSet charList;
    private Character character;
    private DataCenter dataCenter;
    private static TreeMap<Long, Character> characters = new TreeMap<Long, Character>();

    public PacketFormatter() {
    }

    public PacketFormatter(DataCenter pDatCent) {
        dataCenter = pDatCent;
    }

    public static String getISPasswordPacket(String interPass) {
        return "00" + interPass;
    }

    public static String getISServerInfoPacket(byte gameServerId, byte state,
            byte pop, String gameAddress, boolean useIP, short gamePort) {
        return "01" + gameServerId + ";" + state + ";" + pop + ";"
                + gameAddress + ";" + gamePort + ";" + (useIP ? "1" : "0");
    }

    public static String getISUpdateStatePacket(byte state) {
        return "10" + state;
    }

    public String getHelloGamePacket() {
        dataCenter.setIsAuth(true);
        return "HG";
    }

    public String getCharacterNameGenerated() {
        String Voyelles = "aeiouy";
        String Consonnes = "bcdfghjklmnpqrstvwxz";
        String NameGenerated = "";
        int lower = 0;
        int higher = 2;
        int random = (int) (Math.random() * (higher - lower)) + lower;
        int i = (int) Math.floor(Math.random() * 20);
        NameGenerated += Consonnes.toUpperCase().charAt(i);
        i = (int) Math.floor(Math.random() * 6);
        NameGenerated += Voyelles.charAt(i);
        i = (int) Math.floor(Math.random() * 6);
        NameGenerated += Voyelles.charAt(i);
        i = (int) Math.floor(Math.random() * 20);
        NameGenerated += Consonnes.charAt(i);
        i = (int) Math.floor(Math.random() * 20);
        NameGenerated += Consonnes.charAt(i);
        i = (int) Math.floor(Math.random() * 6);
        NameGenerated += Voyelles.charAt(i);
        if (random >= 1) {
            i = (int) Math.floor(Math.random() * 20);
            NameGenerated += Consonnes.charAt(i);
            i = (int) Math.floor(Math.random() * 6);
            NameGenerated += Voyelles.charAt(i);
        }

        return "APK" + NameGenerated;
    }

    public void getLoadCharList() {
        dataCenter.sendPacket("BN");
        dataCenter.sendPacket("BN");
        dataCenter.sendPacket("BN");
        dataCenter.sendPacket("Aq1");
    }

    public String getCharacterList(Account pAccount) {
        String packet = "";
        String packet_build = "";

        if (pAccount == null) {
            dataCenter.setRunning(false);
            GameServer.writeLine("Impossible to get account object : Kick client");

        } else {
            charList = pAccount.getCharList(pAccount.getGuid());

            try {
                int i = 0;
                while (charList.next()) {
                    i++;

                    packet_build += charList.getInt("UniqueID") + ";";
                    packet_build += charList.getString("pseudo") + ";";
                    packet_build += charList.getInt("level") + ";";
                    packet_build += charList.getInt("gfxid") + ";";
                    packet_build += charList.getInt("color1") + ";";
                    packet_build += charList.getInt("color2") + ";";
                    packet_build += charList.getInt("color3") + ";";

                    String equipedItems = charList.getString("items");
                    packet_build += Character.getEquipedItems(equipedItems) + ";";

                    packet_build += charList.getByte("isMerchant") + ";";
                    packet_build += GameConf._gameServerId + ";";
                    packet_build += charList.getInt("isDead") + ";";
                    packet_build += "0;";
                    packet_build += "200";

                    if (!charList.isLast()) {
                        packet_build += "|";
                    }
                }
                packet = "ALK31536000000|" + i + "|" + packet_build;

            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        return packet;
    }

    public String getCharacterData(Account pAccount, long charID) {
        String[] charData = {null};
        String packet = "";

        charData = pAccount.getCharData(pAccount.getGuid(), charID);

        if (charData[0] == null) {
            dataCenter.setRunning(false);
            GameServer.writeLine("Unable to get character data for character "
                    + charID + " Kick client");
        } else {
            // create the character
            character = new Character(charData, dataCenter.getOut());

            // Add character to characters list
            characters.put(character.getEntitieMapGuid(), character);

            // build the packet
            packet += "ASK|";
            packet += charData[0] + "|"; // ID character
            packet += charData[1] + "|"; // pseudo character
            packet += charData[9] + "|"; // level
            packet += charData[4] + "|"; // class
            packet += charData[3] + "|"; // sex
            packet += charData[5] + "|"; // gfxid
            packet += charData[6] + "|"; // color 1
            packet += charData[7] + "|"; // color 2
            packet += charData[8] + "|"; // color 3

            // Inventory
            character.setInventory(charData[12]);
            GameServer.writeLine("Iventory : " + character.getInventory().size());
            packet += Item.formatedIventory(character.getInventory()) /*+ Item.formatedIventory(character.getEquipedItems())*/ + ";"; // inventory
        }

        return packet;
    }

    public void getCreateGame(String name) {
        
        dataCenter.sendPacket("GCK|1|" + name);
        
        dataCenter.sendPacket("AR6bk"); //Activation du mode 8 faces
        
        getStats();

        character.setOnline(true); // Set the status of the character online

        getLifeRestoreTimerStart(false);

        getNewMap();

        try {
            java.net.InetAddress i = java.net.InetAddress.getLocalHost();
            getInfosMessage("189");
            // getInfosMessage("0152;");
            getInfosMessage("0153;" + i.getHostAddress());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public Character getCharacter() {
        return this.character;
    }

    public void getStats() {
        String packet = "As"; // Reset the packet for 'As' packet

        // 'As' packet
        ArrayList<String[]> expData = LoadingData.getExpData();
        // Get level for exp table
        int level = character.getLevel();
        if (level < 1) {
            level = 1;
        } else if (level > expData.size() - 1) {
            level = expData.size() - 1;
        }

        // Get start exp level
        Object[] minExp = expData.get(level - 1);

        // Get end exp level
        Object[] maxExp = expData.get(level);

        // Build the exp packet
        packet += character.getExp() + "," + minExp[1] + "," + maxExp[1] + "|";

        // Get kamas
        packet += character.getKamas() + "|";

        // Get capitals Points
        packet += character.getCaractPoints() + "|"
                + character.getSpellPoints() + "|";

        // Get alignment
        packet += character.getAlignmentType() + "~"
                + character.getAlignmentType() + ","
                + character.getAlignmentLevel() + ","
                + character.getAlignmentGrade() + ","
                + character.getAlignmentHonor() + ","
                + character.getAlignmentDeshonor() + ","
                + character.getAlignmentStatut() + "|";

        // Get PDV's
        ArrayList<String[]> raceData = LoadingData.getRaceData();
        Object[] baseDatas = raceData.get(character.getRace() - 1);

        packet += character.getLife()
                + ","
                + character.getPdvMax(character.getLevel(),
                Integer.parseInt((String) baseDatas[2])) + "|";

        // Get energy
        packet += character.getEnergy() + ",10000|";

        // Get Initiative
        packet += baseDatas[5] + "|"; // TODO : Initiative bonus

        // Get Prospection
        packet += baseDatas[6] + "|"; // TODO : Prospection Bonus

        // Get PA's
        packet += baseDatas[3] + "," + "0,0,0," + baseDatas[3] + "|";

        // Get PM's
        packet += baseDatas[4] + "," + "0,0,0," + baseDatas[4] + "|";

        // Get Strength
        packet += character.getStrength() + ",0,0,0|";

        // Get Vitality
        packet += character.getVitality() + ",0,0,0|";

        // Get Wisdom
        packet += character.getWisdom() + ",0,0,0|";

        // Get Luck
        packet += character.getLuck() + ",0,0,0|";

        // Get Agility
        packet += character.getAgility() + ",0,0,0|";

        // Get Intelligence
        packet += character.getIntelligence() + ",0,0,0|";

        // Get PO
        packet += character.getPo() + ",0,0,0|";

        // Get Creature Invokable
        packet += character.getCreatureInvocable() + ",0,0,0|";

        // Get Bonus Damages
        packet += character.getBonusDo() + ",0,0,0|";

        // Get Bonus Damages Physic
        packet += character.getBonusDoP() + ",0,0,0|";

        // Get Bonus Damages Magic
        packet += character.getBonusDoM() + ",0,0,0|";

        // Get Bonus Damages Percentage
        packet += character.getBonusDoPer() + ",0,0,0|";

        // Get Bonus Trap
        packet += character.getBonusTrap() + ",0,0,0|";

        // Get Bonus Trap Percentage
        packet += character.getBonusTrapPer() + ",0,0,0|";

        // Get Bonus Heal
        packet += character.getBonusHeal() + ",0,0,0|";

        // Get Damages Return
        packet += character.getDamageReturn() + ",0,0,0|";

        // Get Bonus CC
        packet += character.getBonusCC() + ",0,0,0|";

        // Get Bonus EC
        packet += character.getBonusEC() + ",0,0,0|";

        // Get Miss PA
        packet += character.getMissPa() + ",0,0,0|";

        // Get Miss PM
        packet += character.getMissPM() + ",0,0,0|";

        // Get Resist Neutral
        packet += character.getResistNeutral() + ",0,0,0|";

        // Get Resist Neutral Percentage
        packet += character.getResistNeutralPer() + ",0,0,0|";

        // Get Resist Earth
        packet += character.getResistEarth() + ",0,0,0|";

        // Get Resist Earth Percentage
        packet += character.getResistEarthPer() + ",0,0,0|";

        // Get Resist Fire
        packet += character.getResistFire() + ",0,0,0|";

        // Get Resist Fire Percentage
        packet += character.getResistFirePer() + ",0,0,0|";

        // Get Resist Water
        packet += character.getResistWater() + ",0,0,0|";

        // Get Resist Water Percentage
        packet += character.getResistWaterPer() + ",0,0,0|";

        // Get Resist Air
        packet += character.getResistAir() + ",0,0,0|";

        // Get Resist Air Percentage
        packet += character.getResistAirPer() + ",0,0,0|";

        // Get Resist Pvp Neutral
        packet += character.getResistPvpNeutral() + ",0,0,0|";

        // Get Resist Pvp Neutral Percentage
        packet += character.getResistPvpNeutralPer() + ",0,0,0|";

        // Get Resist Pvp Earth
        packet += character.getResistPvpEarth() + ",0,0,0|";

        // Get Resist Pvp Earth Percentage
        packet += character.getResistPvpEarthPer() + ",0,0,0|";

        // Get Resist Pvp Fire
        packet += character.getResistPvpFire() + ",0,0,0|";

        // Get Resist Pvp Fire Percentage
        packet += character.getResistPvpFirePer() + ",0,0,0|";

        // Get Resist Pvp Water
        packet += character.getResistPvpWater() + ",0,0,0|";

        // Get Resist Pvp Water Percentage
        packet += character.getResistPvpWaterPer() + ",0,0,0|";

        // Get Resist Pvp Air
        packet += character.getResistPvpAir() + ",0,0,0|";

        // Get Resist Pvp Air Percentage
        packet += character.getResistPvpAirPer() + ",0,0,0|";

        dataCenter.sendPacket(packet); // Send 'As' packet
    }

    public Map getNewMap() {
        String packet = "GDM|"; // Reset the packet for MapData packet

        // Get map datas loaded
        Hashtable<Integer, Map> getMapDatas = LoadingData.getMapData();
        Map mapDatas = getMapDatas.get(character.getMapID());

        // Create Triggers if not exists
        if (mapDatas.getTriggersDatas().isEmpty()) {
            mapDatas.createTriggers();
        }

        // Create Cells if not exists
        if (mapDatas.getCellsDatas() == null || mapDatas.getCellsDatas().isEmpty()) {
            mapDatas.createCells();
        }

        // Get map id
        packet += mapDatas.getId() + "|";

        // Get created time map
        packet += mapDatas.getDate() + "|";

        // Get CryptKey
        packet += mapDatas.getKey();

        dataCenter.sendPacket(packet); // Send GDM packet

        return mapDatas;

    }

    public void getBasicTime() {
        String packet = "BT";

        packet += System.currentTimeMillis(); // Get the time in milliseconds

        dataCenter.sendPacket(packet);
    }

    public void getSubscribeChannel() {
        String packet = "cC+*#%!pi$:?^";
        dataCenter.sendPacket(packet); // Send cC packet
    }

    public void getInfosMessage(String param) {
        String packet = "Im" + param;

        dataCenter.sendPacket(packet);
    }

    public void getLifeRestoreTimerStart(boolean sit) {
        String packet = "ILS"; // Reset the packet for Gain PDV Interval
        
        packet += GameConf._gainPdvInterval;

        dataCenter.sendPacket(packet); // Send 'ILS' packet
    }

    public void getFightCountOnMap(Map map) {
        String packet = "fC";

        packet += map.getFightCount();

        dataCenter.sendPacket(packet); // Send 'fC' packet
    }

    public void getGMData() {
        // add character on the map
        Hashtable<Integer, Map> getMapDatas = LoadingData.getMapData();
        Map mapDatas = getMapDatas.get(character.getMapID());

        mapDatas.addCharacterOnMap(character);

        // Get all characters on the map
        Hashtable<Long, Character> onMapCharacters = mapDatas.getCharacterOnMap();

        Enumeration<Long> enumCharacters = onMapCharacters.keys();

        while (enumCharacters.hasMoreElements()) {
            long key = (Long) enumCharacters.nextElement(); // Next Character
            Character onMapCharacterDatas = onMapCharacters.get(key);

            if (onMapCharacterDatas == null) {
                GameServer.writeLine("onMapCharacterDatas is null");
            }

            // FIXME: Add column direction on character table
            String packet = "GM|"; // Reset the packet

            packet += "+" + onMapCharacterDatas.getCellID() + ";"
                    + GameConf._startDir
                    + ";0;"
                    + onMapCharacterDatas.getEntitieMapGuid() + ";"
                    + onMapCharacterDatas.getName() + ";"
                    + onMapCharacterDatas.getRace() + ";"
                    + onMapCharacterDatas.getGfxid() + "^" + onMapCharacterDatas.getSize() + ";"
                    + onMapCharacterDatas.getSex() + ";"
                    + onMapCharacterDatas.getAlignmentType() + ","
                    + "0," + onMapCharacterDatas.getAlignmentStatut() + ","
                    + onMapCharacterDatas.getEntitieMapGuid() + ";"
                    + onMapCharacterDatas.getColor1() + ";"
                    + onMapCharacterDatas.getColor2() + ";"
                    + onMapCharacterDatas.getColor3() + ";"
                    + Item.formatEquipedItem(onMapCharacterDatas.getEquipedItems()) + ";"
                    + (onMapCharacterDatas.getLevel() > 99 ? (onMapCharacterDatas.getLevel() > 199 ? "2" : "1") : "0") + ";"
                    + onMapCharacterDatas.getLastEmote() +";" + // Emote 
                    ";" + // Emote timer
                    "Guild name;" + // Guild name 
                    "1;" + // Guild emblem
                    "0;" + // Restriction
                    ";" + // On mount
                    ";;";

            updateGMDatas("+", character);
            dataCenter.sendPacket(packet); // Send one 'GM' packet
        }
    }

    public void updateGMDatas(String action, Character pCharacter) {
        String packet = "GM|";

        switch (action.charAt(0)) {
            case '+': // Add character on the map
            case '~': // Refresh character on the map
                packet += action.charAt(0) + pCharacter.getCellID() + ";"
                        + GameConf._startDir
                        + ";0;"
                        + pCharacter.getEntitieMapGuid() + ";"
                        + pCharacter.getName() + ";"
                        + pCharacter.getRace() + ";"
                        + pCharacter.getGfxid() + "^" + pCharacter.getSize() + ";"
                        + pCharacter.getSex() + ";"
                        + pCharacter.getAlignmentType() + ","
                        + "0," + pCharacter.getAlignmentStatut() + ","
                        + pCharacter.getEntitieMapGuid() + ";"
                        + pCharacter.getColor1() + ";"
                        + pCharacter.getColor2() + ";"
                        + pCharacter.getColor3() + ";"
                        + Item.formatEquipedItem(pCharacter.getEquipedItems()) + ";"
                        + (pCharacter.getLevel() > 99 ? (pCharacter.getLevel() > 199 ? "2" : "1") : "0") + ";"
                        + pCharacter.getLastEmote() + ";" + // Emote 
                        ";" + // Emote timer
                        "Guild name;" + // Guild name 
                        "1;" + // Guild emblem
                        "0;" + // Restriction
                        ";" + // On mount
                        ";;";

                dataCenter.sendPacketToMap(character.getMapID(), packet); // Send 'GM' packet

                break;

            case '-':
                packet += "-" + pCharacter.getEntitieMapGuid();
                dataCenter.sendPacketToMap(character.getMapID(), packet); // Send
                break;
        }
    }

    public void getGameAction(String packet) {
        int actionType;

        try {
            actionType = Integer.parseInt(packet.substring(2, 5));
            GameServer.writeLine("GA Type : " + actionType);
        } catch (NumberFormatException e) {
            return;
        }
        ;

        switch (actionType) {
            case 1:
                String path = packet.substring(5);

                String finalPath = "a" + Cell.encodeCellID(character.getCellID());

                finalPath += path;
                short endCell = Cell.decodeCellID(path.substring(path.length() - 2));
                if (character.getLastEmote() != 0) {
                    character.setLastEmote(0);
                    getLifeRestoreTimerStart(false);
                }
               // dataCenter.sendPacket("GA001afibfM"); //Ca empéche de bloquer le client
                //dataCenter.sendPacket("BN");
                dataCenter.sendPacketToMap(character.getMapID(), "GA0;" + "1;" + character.getEntitieMapGuid() + ";" + finalPath);
                character.setCellID(endCell);

                break;
                
            case 900:
                long targetChallenge;
                
                targetChallenge = Integer.parseInt(packet.substring(5));
                GameServer.writeLine(character.getName() + "(" + character.getEntitieMapGuid() + ") launch challenge against " + characters.get(targetChallenge).getName() + "(" + targetChallenge+ ")");
                dataCenter.sendPacket("GA;900;"+ character.getEntitieMapGuid() +";" + targetChallenge);
                dataCenter.sendTargetedPacket(characters.get(targetChallenge).getOut(), "GA;900;"+ character.getEntitieMapGuid() +";" + targetChallenge);
                
                break;

            case 901:
                //acceptChallenge
                
            	break;

            case 902:
                //refuseChallenge
                
            	break;
                
            case 903:
                //joinChallenge
            	
            	break;
        }
    }

    public void sendMessageToMap(String message) {
        String packet = "cMK|";

        packet += character.getEntitieMapGuid() + "|";
        packet += character.getName() + "|";
        packet += message;

        dataCenter.sendPacketToMap(character.getMapID(), packet);
    }

    public void sendAdminMessage(String message) {
        if (dataCenter.getAccount().getGmLevel() > 0) {
            String packet = "cMK@|";

            packet += character.getEntitieMapGuid() + "|";
            packet += character.getName() + "|";
            packet += message;

            dataCenter.sendPacketToAdmins(packet);
        } else {
            dataCenter.sendPacket("cs<font color='#FF0000'>Vous n'êtes pas autorisé à utiliser ce canal !</font>");
        }
    }

    public void sendRecruitmentMessage(String message) {
        String packet = "cMK?|";

        packet += character.getEntitieMapGuid() + "|";
        packet += character.getName() + "|";
        packet += message;

        dataCenter.sendPacketToAllClients(packet);
    }

    public void sendTradeMessage(String message) {
        String packet = "cMK:|";

        packet += character.getEntitieMapGuid() + "|";
        packet += character.getName() + "|";
        packet += message;

        dataCenter.sendPacketToAllClients(packet);
    }

    public void sendAlignmentMessage(String message) {
        String packet = "cMK!|";

        packet += character.getEntitieMapGuid() + "|";
        packet += character.getName() + "|";
        packet += message;

        dataCenter.sendPacketToAllClients(packet);
    }

    public void sendGroupMessage(String message) {
        getInfosMessage("11");
        /*
         * String packet = "cMK$|";
         * 
         * packet+= character.getEntitieMapGuid() + "|"; packet +=
         * character.getName() + "|"; packet += message;
         * dataCenter.sendPacketToAllClients(packet);
         */
    }

    public void sendPrivateMessage(long targetID, String message)// FIXME :																
    // delivery
    {
        String packet = "cMKF|";

        packet += character.getEntitieMapGuid() + "|";
        packet += character.getName() + "|";
        packet += message;

        dataCenter.sendTargetedPacket(characters.get(targetID).getOut(), packet);
    }

    public void sendIncarnamMessage(String message) {
        String packet = "cMK¤|";

        packet += character.getEntitieMapGuid() + "|";
        packet += character.getName() + "|";
        packet += message;

        dataCenter.sendPacketToAllClients(packet);
    }

    public void changeMap(int oldMapID, int newMapID, short cellID) {
        if (oldMapID == newMapID) // Go to the same map
        {
            // Delete the character from the map
            updateGMDatas("-", character);

            // Move the character
            character.setCellID(cellID);

            // Display it a the new position
            updateGMDatas("+", character);

            return;
        }
        String packet = "GDM|";

        // Get map datas loaded
        Hashtable<Integer, Map> getMapDatas = LoadingData.getMapData();

        // Map exist?
        if (!getMapDatas.containsKey(newMapID)) {
            dataCenter.sendPacket("cs<font color='#FF0000'>Map " + newMapID + " doesn't exist !</font>");

            return;
        }

        // Delete character form old map
        Map oldMap = getMapDatas.get(oldMapID);
        oldMap.deleteCharacterOnMap(character);

        // Update GMDatas on old map
        updateGMDatas("-", character);

        // Get new map
        Map mapDatas = getMapDatas.get(newMapID);

        // Change current character map id and cell id
        character.setMapID(newMapID);
        character.setCellID(cellID);

        // Create Triggers if not exists
        if (mapDatas.getTriggersDatas().isEmpty()) {
            mapDatas.createTriggers();
        }

        // Create Cells if not exists
        if (mapDatas.getCellsDatas() == null || mapDatas.getCellsDatas().isEmpty()) {
            mapDatas.createCells();
        }

        // Update GMDatas
        updateGMDatas("+", character);

        // Get map id
        packet += mapDatas.getId() + "|";

        // Get created time map
        packet += mapDatas.getDate() + "|";

        // Get CryptKey
        packet += mapDatas.getKey();

        dataCenter.sendPacket(packet); // Send GDM packet

    }

    public void getEndMovements() 
    {
    	dataCenter.sendPacket("BN");
        Trigger cellTrigger;
        if((cellTrigger = Cell.getCellAction(character.getMapID(), character.getCellID())) != null) // On a cell trigger 
        {
            changeMap(cellTrigger.getCurrentMapID(), cellTrigger.getToMapID(), cellTrigger.getToCellID());
        }
        else if((!LoadingData.getMapData().get(character.getMapID()).getCellsDatas().get(Short.parseShort(Integer.toString(character.getCellID()))).getMonsterGroups().isEmpty())) // On a monster group
        {
        	Map currentMap = LoadingData.getMapData().get(character.getMapID());
        	long groupID;
        	groupID = currentMap.getCellsDatas().get(Short.parseShort(Integer.toString(character.getCellID()))).getMonsterGroups().get(0);
        	
        	GameServer.writeLine("You are on a group monster (" + groupID + ")");
        	
        	Fight fight = new Fight(character, (byte)3, currentMap.getMonstersOnMap().get(groupID).getCellID());
        	
        	currentMap.addFightOnMap(fight);
        	dataCenter.sendPacketToMap(character.getMapID(), "fC" + LoadingData.getMapData().get(character.getMapID()).getFightCount());
        	
        	dataCenter.sendPacket("GJK2|0|1|0|2|3");
        	
        	if(currentMap.getPlacesTeamOne().isEmpty() || currentMap.getPlacesTeamTwo().isEmpty())
        		currentMap.generatePlaces();
        	
        	dataCenter.sendPacket("GP" + currentMap.getFightPlaces() + "|0");
        	
        	dataCenter.sendPacket("GA;950;29;29;3;0;");
        	dataCenter.sendPacket("GA;950;29;29;8;0;");
        	dataCenter.sendPacket("GM|-");
        	
        	dataCenter.sendPacket("GM|+" + fight.getRandomPlace(currentMap, (byte)1) + ";1;0;" + character.getEntitieMapGuid() + ";" + character.getName() + ";" + character.getRace() + ";" + character.getGfxid() + "^" + character.getSize() + ";" + character.getSex() + ";" + character.getLevel() + ";" + character.getAlignmentType() + ",0," + (character.getAlignmentStatut() ? "1" : "0") + "," + character.getEntitieMapGuid() + ";" + character.getColor1() + ";" + character.getColor2() + ";" + character.getColor3() + ";,,,,;" + character.getLife() + ";" + character.getPa() + ";" + character.getPm() + ";" + character.getResistNeutral() + ";" + character.getResistEarth() + ";" + character.getResistFire() + ";" + character.getResistWater() + ";" + character.getResistAir() + ";" + character.getMissPa() + ";" + character.getMissPM() + ";0;;");
        	
        	Iterator<Monster> vIter = currentMap.getMonstersOnMap().get(groupID).getMonsters().iterator();
        	int i = 0;
        	
        	while(vIter.hasNext())
        	{
        		i++;
        		Monster monster = vIter.next();
        		
        		dataCenter.sendPacket("GM|+" + fight.getRandomPlace(currentMap, (byte)2) + ";1;0;-" + i + ";" + monster.getEntitieMapGuid() + ";-2;" + monster.getGfxid() + "^100;" + monster.getGrade() + ";" + monster.getColors().replace(",", ";") + ";0,0,0,0;" + monster.getVitality() + ";" + monster.getPa() + ";" + monster.getPm() + ";1");
        	}
        	
        	/* SEND >> GPeBenePe3eQeCe4fg|dqdcdEdSdbcZdpdD|0
        		SEND >> GA;950;29;29;3;0;
        		SEND >> GA;950;29;29;8;0;
        		SEND >> GM|- 
        		SEND >> GM|+284;5;0;29;Bivulehi;11;111^100;1;300;0,0,0,0;-1;-1;-1;,,,,;2500;7;3;
				0;0;0;0;0;0;0;0;;
				SEND >> GM|+284;5;0;29;Bivulehi;11;111^100;1;300;0,0,0,0;-1;-1;-1;,,,,;2500;7;3;
				0;0;0;0;0;0;0;0;;
				SEND >> GM|+221;1;0;-1;653;-2;1335^120;4;f14107;eef2fc;-1,0,0,0;0;160;6;3;1
				SEND >> GM|+222;1;0;-2;653;-2;1335^120;4;f14107;eef2fc;-1,0,0,0;0;160;6;3;1
				SEND >> GM|+236;1;0;-3;654;-2;1335^120;4;1494ea;eef2fc;-1,0,0,0;0;45;8;4;1
				SEND >> GM|+194;1;0;-4;655;-2;1335^120;4;aa5a46;eef2fc;-1,0,0,0;0;210;4;3;1
				SEND >> GM|+208;1;0;-5;654;-2;1335^120;4;1494ea;eef2fc;-1,0,0,0;0;45;8;4;1 */
        	//"GJK"+state+"|"+cancelBtn+"|"+duel+"|"+spec+"|"+time+"|"+type
        }
    }

    public void GetMonsterGroupsGMDatas() // FIXME : Debug this packet
    {
    	GameServer.writeLine("Number Groups " + LoadingData.getMapData().get(character.getMapID()).getMonstersOnMap().size());
    	try
        {
	        if(!LoadingData.getMapData().get(character.getMapID()).isMonsterLoaded())
	    	{
	        	Hashtable<Long, MonsterGroup> groupList = LoadingData.getMapData().get(character.getMapID()).getMonstersOnMap(); // Get Groups monster on the map
	    		Iterator<MonsterGroup> vIter = groupList.values().iterator();
		        
		        while(vIter.hasNext())
		        {
		        	MonsterGroup monsterGroup = vIter.next();
		        	
		        	if(LoadingData.getMapData().get(character.getMapID()).getCellsDatas().size() == 0 || LoadingData.getMapData().get(character.getMapID()).getCellsDatas() == null)
		        	{
		        		GameServer.writeLine("Unable to create group monster on map because no cells created");
		        	}
		        	else
		        	{
		        		short rCellID;
		        		
		        		do
		        		{
		        			rCellID = LoadingData.getMapData().get(character.getMapID()).getRandomCellID();
		        		}while(!LoadingData.getMapData().get(character.getMapID()).getCellsDatas().get(rCellID).isWalkable());
		        		
		        			LoadingData.getMapData().get(character.getMapID()).getCellsDatas().get(rCellID).addMonsterGroups(monsterGroup.getEntitieMapGuid());
		        			monsterGroup.setCellID(rCellID);
		        			monsterGroup.setOrientation((byte)Maths.randomBetween(0, 3));
		        	}
		        }
		        
		        LoadingData.getMapData().get(character.getMapID()).setMonsterLoaded(true);
	    	}
        }
        catch(Exception x){GameServer.writeLine("Map " + character.getMapID() + " has no mobs");
        }
        
    	String packet = "GM|+"; // Initialize packet
    	
    	Iterator<MonsterGroup> vIter = LoadingData.getMapData().get(character.getMapID()).getMonstersOnMap().values().iterator(); // Create iterator on group monster
    	
    	while(vIter.hasNext()) // If have other group
    	{
    		MonsterGroup group = vIter.next(); // Get the Group monster
    		Iterator<Monster> gMonster = group.getMonsters().iterator(); // Create the iterator to get monsters in the group
    		
    		String packetID = "";
        	String packetGfxid = "";
        	String packetLevel = "";
        	String packetColor ="";
    		while(gMonster.hasNext()) // If have other monster in the group
    		{
                        
    			Monster monster = gMonster.next(); // Get the monster
    			
    			// Set monsters id
    			packetID += monster.getEntitieMapGuid();
    			packetID += (gMonster.hasNext()) ? "," : "";
                        
    			// Set monsters gfxid
    			packetGfxid += monster.getGfxid() + "^100";
    			packetGfxid += (gMonster.hasNext()) ? "," : "";
    			
    			// Set monsters level
    			packetLevel += monster.getLevel();
    			packetLevel += (gMonster.hasNext()) ? "," : "";
    			
    			// Set monsters colors
    			packetColor += monster.getColors() + ";0,0,0,0";
    			packetColor += (gMonster.hasNext()) ? "," : "";
    		}
    		
        	packet += group.getCellID() + ";";
        	packet += group.getOrientation() + ";0;";
        	packet += group.getEntitieMapGuid() + ";";
        	packet += packetID + ";";
        	packet += "-3;"; //FIXME: id du mob ?
        	packet += packetGfxid + ";";
        	packet += packetLevel + ";";
        	packet += packetColor + ";";
        	packet += (vIter.hasNext()) ? "|+" : "";
    	}
    	
    	dataCenter.sendPacket(packet);
    }
    
    public void itemManage(String action, Item item) // FIXME : To add or remove an item
    {
    }

    public long getCharacterByName(String charName) {
        long result = -1;
        Iterator<Character> vIter = characters.values().iterator();
        Iterator<Long> kIter = characters.keySet().iterator();

        while (vIter.hasNext() && kIter.hasNext()) {
            Character valueI = vIter.next();
            long keyI = kIter.next();

            if (valueI.getName().equals(charName)) {
                result = keyI;
            }
        }

        return result;
    }

    public static TreeMap<Long, Character> getCharacters() {
        return characters;
    }

    public void removeFormCharactersList() {
        characters.remove(character.getEntitieMapGuid());
    }
}